
package net.ifilm.main;


import net.ifilm.common.Constants;
import net.ifilm.common.SpiderCache;
import net.ifilm.common.ThreadPool;
import net.ifilm.db.DBConnectionUtil;
import net.ifilm.db.DBExecutor;
import net.ifilm.domain.Configuration;
import net.ifilm.domain.Message;
import net.ifilm.service.IWebSiteService;
import net.ifilm.service.XddyWebSiteService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Properties;

/**
 *
 * @author wangjunneil@gmail.com
 */
public final class QvodSpider {

    private static final Log log = LogFactory.getLog(QvodSpider.class);

    private static final String CONFIG_FILE_NAME = "config.properties";

    private Configuration configuration = null;

    private boolean singlePage = false; // 是否是单个页面的处理请求

    public QvodSpider() { }

    private void initialize() throws Exception {
        long startTime = System.currentTimeMillis();

        initializeConfiguration();
        initializeDbCache();
        initializeThreadPool();

        if (log.isInfoEnabled()) {
            log.info("deamon server initialize complate, waste time " + (System.currentTimeMillis() - startTime) + " ms");
        }
    }

    private void initializeConfiguration() throws Exception {
        log.info("System is Running...");

        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(CONFIG_FILE_NAME);
        if (inputStream == null) {
            throw new FileNotFoundException("Cann't find " + CONFIG_FILE_NAME + " in classpath.");
        }

        Properties props = new Properties();
        props.load(inputStream);

        configuration = new Configuration();
        configuration.setDbDriver(props.getProperty("db.driver"));
        configuration.setDbUrl(props.getProperty("db.url"));
        configuration.setDbUser(props.getProperty("db.user"));
        configuration.setDbPass(props.getProperty("db.pass"));
        configuration.setDownloadPath(props.getProperty("download.path"));
        configuration.setSiteDomain(props.getProperty("website.domain"));

        String siteKey = props.getProperty("website.key");
        if (siteKey == null || "".equals(siteKey))
            throw new RuntimeException("websizte.key cann't is null in " + CONFIG_FILE_NAME);
        configuration.setSiteKey(siteKey);
        String pageList = props.getProperty(siteKey + ".page");
        if (pageList != null && !"".equals(pageList)) {
            singlePage = true;
            configuration.setSitePages(pageList);
        }
        else {
            String sitelist = props.getProperty(siteKey + ".list");
            configuration.setSitelist(sitelist);
        }

        int threadNum = 3; // default thread num is 3
        try {
            threadNum = Integer.parseInt(props.getProperty("thread.num"));
        } catch (NumberFormatException e) {
            if (log.isWarnEnabled()) {
                log.warn(CONFIG_FILE_NAME + " configuration error, " + e.toString());
            }
            // ignore
        }
        configuration.setThreadNum(threadNum);

        log.debug(configuration.toString());
        log.info("initial cnfiguration information complate");
    }

    private void initializeDbCache() throws Exception {
        log.info("loading cache data ...... please wait ......");

        DBConnectionUtil.getInstance().configuration(configuration);
        SpiderCache spiderCache = SpiderCache.getInstance();
        spiderCache.initialCache();

        if (log.isInfoEnabled()) {
            log.info("database initialize complate, filmNameList is "
                    + spiderCache.getFilmNameMap().size() + ", reverseFilmNamelist is "
                    + spiderCache.getReverseFilmNameMap().size() + ", filmActorList is "
                    + spiderCache.getFilmActorMap().size());
        }
    }

    private void initializeThreadPool() throws Exception {
        ThreadPool threadPool = new ThreadPool(configuration.getThreadNum());
        threadPool.start();

        log.info("the thread of thread pool has already initialize complate");
    }

    private void singleFilmProcess() {
        String pagelist = configuration.getSitePages();

        DBExecutor dbExecutor = new DBExecutor();
        if (pagelist.indexOf(Constants.SEPARATE) != -1) {
            String[] pages = pagelist.split(Constants.SEPARATE);

            Message message = null;
            for (String page : pages) {
                message = new Message();
                message.setDbExecutor(dbExecutor);
                message.setDownloadPath(configuration.getDownloadPath());
                message.setDomain(configuration.getSiteDomain());
                message.setFilmLinkPage(page);

                Constants.messageQueue.put(message);
            }
        } else {
            Message message = new Message();
            message = new Message();
            message.setDbExecutor(dbExecutor);
            message.setDownloadPath(configuration.getDownloadPath());
            message.setDomain(configuration.getSiteDomain());
            message.setFilmLinkPage(pagelist);

            Constants.messageQueue.put(message);
        }
    }

    public void process() throws Exception {
        if (singlePage) {
            singleFilmProcess();
        } else {
            /*
             * 针对不同的SiteKey创建不同的站点业务方法
             */
            IWebSiteService iWebSiteService = null;
            String siteKey = configuration.getSiteKey();
            if (Constants.KEY_XDDY.equals(siteKey)) {
                iWebSiteService = new XddyWebSiteService(configuration);
                iWebSiteService.process();

            }

            if (log.isInfoEnabled()) {
                log.info("the " + siteKey + " website engine service prepare start");
            }
        }
    }

    public void startWork() {
        Runnable worker = new Runnable() {
            @Override
            public void run() {
                QvodSpider spider = new QvodSpider();
                try {
                    spider.initialize();
                    spider.process();
                } catch (Exception e) {
                    log.error(e.toString());
                    e.printStackTrace();

                    System.exit(1);
                }
            }
        };

        ThreadGroup threads = new ThreadGroup("QSpider");
        new Thread(threads, worker, "main").start();
    }

    public static void main(String[] args) {
        Runnable worker = new Runnable() {
            @Override
            public void run() {
                QvodSpider spider = new QvodSpider();
                try {
                    spider.initialize();
                    spider.process();
                } catch (Exception e) {
                    log.error(e.toString());
                    e.printStackTrace();

                    System.exit(1);
                }
            }
        };

        ThreadGroup threads = new ThreadGroup("QSpider");
        new Thread(threads, worker, "main").start();
    }

}

